package com.ling.feign.plus.model;

import com.google.gson.annotations.SerializedName;
import com.ling.common.exception.BaseBusinessException;
import com.ling.common.exception.DefaultBusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Objects;

public class BusinessExceptionModel implements Serializable {
    private static final long serialVersionUID = 1L;
    private static final Logger log = LoggerFactory.getLogger(BusinessExceptionModel.class);
    @SerializedName("code")
    private Integer code;
    @SerializedName("msg")
    private String msg;
    @SerializedName("className")
    private final String className;
    @SerializedName("stackTrace")
    private StackTraceElement[] stackTrace;

    public BusinessExceptionModel(String className) {
        this.className = className;
    }

    public Integer getCode() {
        return code;
    }

    public BusinessExceptionModel setCode(Integer code) {
        this.code = code;
        return this;
    }

    public String getMsg() {
        return msg;
    }

    public BusinessExceptionModel setMsg(String msg) {
        this.msg = msg;
        return this;
    }


    public String getClassName() {
        return className;
    }


    public StackTraceElement[] getStackTrace() {
        return stackTrace;
    }

    public BusinessExceptionModel setStackTrace(StackTraceElement[] stackTrace) {
        this.stackTrace = stackTrace;
        return this;
    }

    public <T extends BaseBusinessException> T getBusinessException() {
        try {
            Class<?> clazz = Class.forName(className);
            Constructor<? extends BaseBusinessException> constructor =
                    (Constructor<? extends BaseBusinessException>) clazz.getConstructor();
            T exception = (T) constructor.newInstance();
            exception.setCode(this.code);
            exception.setMsg(this.msg);
            if (Objects.nonNull(stackTrace)) {
                exception.setStackTrace(stackTrace);
            }
            return exception;
        } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            log.error("异常Class'{}'BaseException#BaseException()构造器", className);
            throw new DefaultBusinessException();
        }
    }

}